#!/usr/bin/env python3
"""
API修复和测试脚本
检查API_README.md中的接口并修复问题
"""

import os
import sys
import json
import time
import subprocess
import threading
import requests
from datetime import datetime

class APIFixAndTest:
    def __init__(self):
        self.base_url = "http://localhost:8000"
        self.admin_token = "admin_secret_token_2024"
        self.server_process = None
        self.test_results = []
        
    def check_dependencies(self):
        """检查依赖"""
        print("🔍 检查依赖...")
        
        # 检查Python模块
        required_modules = [
            'fastapi', 'uvicorn', 'sqlalchemy', 'pydantic', 
            'requests', 'python_multipart'
        ]
        
        missing_modules = []
        for module in required_modules:
            try:
                __import__(module.replace('-', '_'))
                print(f"✅ {module}")
            except ImportError:
                print(f"❌ {module} - 缺失")
                missing_modules.append(module)
        
        if missing_modules:
            print(f"\n安装缺失的模块:")
            print(f"pip install {' '.join(missing_modules)}")
            return False
        
        return True
    
    def check_files(self):
        """检查必要文件"""
        print("\n📁 检查文件...")
        
        required_files = [
            'backend/main.py',
            'backend/database.py', 
            'backend/models.py',
            'backend/schemas.py',
            'backend/crud.py',
            'backend/requirements.txt'
        ]
        
        missing_files = []
        for file_path in required_files:
            if os.path.exists(file_path):
                print(f"✅ {file_path}")
            else:
                print(f"❌ {file_path} - 缺失")
                missing_files.append(file_path)
        
        return len(missing_files) == 0
    
    def fix_import_issues(self):
        """修复导入问题"""
        print("\n🔧 检查和修复导入问题...")
        
        # 检查backend/__init__.py
        init_file = 'backend/__init__.py'
        if not os.path.exists(init_file):
            print(f"创建 {init_file}")
            with open(init_file, 'w') as f:
                f.write('# Backend package\n')
        
        # 检查main.py的导入
        try:
            sys.path.insert(0, os.getcwd())
            from backend.main import app
            print("✅ 导入backend.main.app成功")
            return True
        except Exception as e:
            print(f"❌ 导入失败: {e}")
            return False
    
    def start_server_background(self):
        """在后台启动服务器"""
        print("\n🚀 启动后台服务器...")
        
        try:
            # 使用subprocess启动服务器
            cmd = [
                sys.executable, '-m', 'uvicorn', 
                'backend.main:app', 
                '--host', '0.0.0.0', 
                '--port', '8000'
            ]
            
            self.server_process = subprocess.Popen(
                cmd,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                cwd=os.getcwd()
            )
            
            # 等待服务器启动
            print("等待服务器启动...")
            time.sleep(5)
            
            # 检查进程是否还在运行
            if self.server_process.poll() is None:
                print("✅ 服务器进程启动成功")
                return True
            else:
                stdout, stderr = self.server_process.communicate()
                print(f"❌ 服务器启动失败")
                print(f"stdout: {stdout.decode()}")
                print(f"stderr: {stderr.decode()}")
                return False
                
        except Exception as e:
            print(f"❌ 启动服务器异常: {e}")
            return False
    
    def test_server_connection(self):
        """测试服务器连接"""
        print("\n🔗 测试服务器连接...")
        
        max_retries = 10
        for i in range(max_retries):
            try:
                response = requests.get(f"{self.base_url}/health", timeout=5)
                if response.status_code == 200:
                    print("✅ 服务器连接成功")
                    return True
            except:
                pass
            
            print(f"重试 {i+1}/{max_retries}...")
            time.sleep(2)
        
        print("❌ 无法连接到服务器")
        return False
    
    def test_api_endpoints(self):
        """测试API端点"""
        print("\n🧪 测试API端点...")
        
        # 定义要测试的端点
        endpoints = [
            # 基础端点
            ("GET", "/health", None, None, "健康检查"),
            ("GET", "/", None, None, "根路径"),
            
            # 学生端API
            ("GET", "/api/questions", None, None, "获取题目列表"),
            ("GET", "/api/scores/1", None, None, "获取班级成绩"),
            ("GET", "/api/class-analysis/1", None, None, "班级分析"),
            
            # 管理员API
            ("GET", "/admin/questions", {"Authorization": f"Bearer {self.admin_token}"}, None, "获取所有题目"),
            ("GET", "/admin/question-banks", {"Authorization": f"Bearer {self.admin_token}"}, None, "获取所有题库"),
            ("GET", "/admin/question-banks/active", {"Authorization": f"Bearer {self.admin_token}"}, None, "获取激活题库"),
        ]
        
        results = []
        for method, path, headers, data, description in endpoints:
            success = self._test_single_endpoint(method, path, headers, data, description)
            results.append((description, success))
        
        # 统计结果
        total = len(results)
        passed = sum(1 for _, success in results if success)
        
        print(f"\n📊 测试结果: {passed}/{total} 通过")
        
        # 显示失败的测试
        failed = [(desc, success) for desc, success in results if not success]
        if failed:
            print("\n❌ 失败的测试:")
            for desc, _ in failed:
                print(f"  - {desc}")
        
        return passed, total
    
    def _test_single_endpoint(self, method, path, headers, data, description):
        """测试单个端点"""
        url = f"{self.base_url}{path}"
        
        try:
            if method == "GET":
                response = requests.get(url, headers=headers, timeout=10)
            elif method == "POST":
                response = requests.post(url, headers=headers, json=data, timeout=10)
            else:
                print(f"❌ 不支持的方法: {method}")
                return False
            
            success = response.status_code in [200, 201]
            status = "✅" if success else "❌"
            
            print(f"{status} {method} {path} - {description} ({response.status_code})")
            
            return success
            
        except Exception as e:
            print(f"❌ {method} {path} - {description} (异常: {str(e)[:50]})")
            return False
    
    def generate_api_issues_report(self):
        """生成API问题报告"""
        print("\n📋 生成API问题报告...")
        
        # 检查API_README.md中列出的端点
        api_endpoints_from_readme = [
            # 学生端API
            "/api/questions",
            "/api/submit", 
            "/api/scores/{class_id}",
            "/api/class-analysis/{class_id}",
            "/api/student-trajectory/{class_id}/{student_name}",
            "/api/error-analysis/{class_id}",
            "/api/teaching-suggestions/{class_id}",
            "/api/student-records",
            
            # 教师端API
            "/api/teacher/dashboard",
            "/api/teacher/dashboard/overview",
            "/api/teacher/dashboard/students",
            "/api/teacher/dashboard/errors", 
            "/api/teacher/dashboard/suggestions",
            
            # 管理员API
            "/admin/questions",
            "/admin/questions/{question_id}",
            "/admin/questions/create",
            "/admin/question-banks",
            "/admin/question-banks/active",
            "/admin/question-banks/{bank_id}",
            "/admin/ai-generate",
            "/admin/class-config",
        ]
        
        report = {
            "timestamp": datetime.now().isoformat(),
            "total_endpoints_in_readme": len(api_endpoints_from_readme),
            "endpoints": api_endpoints_from_readme,
            "recommendations": [
                "确保所有依赖已安装: pip install -r backend/requirements.txt",
                "检查数据库文件是否存在和可访问",
                "验证环境变量配置",
                "确保端口8000未被占用",
                "检查防火墙设置"
            ]
        }
        
        with open('api_issues_report.json', 'w', encoding='utf-8') as f:
            json.dump(report, f, ensure_ascii=False, indent=2)
        
        print("✅ 报告已保存到: api_issues_report.json")
    
    def cleanup(self):
        """清理资源"""
        if self.server_process:
            print("\n🛑 停止服务器...")
            self.server_process.terminate()
            self.server_process.wait()
    
    def run_full_test(self):
        """运行完整测试"""
        print("🎯 API修复和测试工具")
        print("="*50)
        
        try:
            # 1. 检查依赖
            if not self.check_dependencies():
                print("❌ 依赖检查失败")
                return False
            
            # 2. 检查文件
            if not self.check_files():
                print("❌ 文件检查失败")
                return False
            
            # 3. 修复导入问题
            if not self.fix_import_issues():
                print("❌ 导入修复失败")
                return False
            
            # 4. 启动服务器
            if not self.start_server_background():
                print("❌ 服务器启动失败")
                return False
            
            # 5. 测试连接
            if not self.test_server_connection():
                print("❌ 服务器连接失败")
                return False
            
            # 6. 测试API端点
            passed, total = self.test_api_endpoints()
            
            # 7. 生成报告
            self.generate_api_issues_report()
            
            print(f"\n🎉 测试完成! {passed}/{total} 个端点通过测试")
            
            if passed == total:
                print("✅ 所有API接口工作正常!")
            else:
                print("⚠️  部分API接口需要修复")
            
            return True
            
        except KeyboardInterrupt:
            print("\n⚠️  测试被用户中断")
            return False
        except Exception as e:
            print(f"\n❌ 测试过程中发生异常: {e}")
            return False
        finally:
            self.cleanup()

def main():
    tester = APIFixAndTest()
    tester.run_full_test()

if __name__ == "__main__":
    main()
